// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
// SPDX-License-Identifier: MIT

package logger

import (
	"bytes"
	"errors"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"

	"github.com/sirupsen/logrus"
)

func TestNew(t *testing.T) {
	logger := New()
	if logger == nil {
		t.Fatal("Expected logger to be created, got nil")
	}

	// 验证实现了Logger接口
	_, ok := logger.(Logger)
	if !ok {
		t.Error("Expected logger to implement Logger interface")
	}

	// 验证基本方法存在
	var buf bytes.Buffer
	logger.SetOutput(&buf)
	logger.Info("test message")

	output := buf.String()
	if !strings.Contains(output, "test message") {
		t.Error("Expected logger to output test message")
	}
}

func TestNewWithFile(t *testing.T) {
	// 创建临时目录
	tmpDir, err := os.MkdirTemp("", "test_logger_")
	if err != nil {
		t.Fatalf("Failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	logFile := filepath.Join(tmpDir, "test.log")

	// 创建带文件的日志器
	logger, err := NewWithFile(logFile, "info")
	if err != nil {
		t.Fatalf("Failed to create logger with file: %v", err)
	}

	if logger == nil {
		t.Fatal("Expected logger to be created, got nil")
	}

	// 验证实现了Logger接口
	_, ok := logger.(Logger)
	if !ok {
		t.Error("Expected logger to implement Logger interface")
	}

	// 测试写入文件
	logger.Info("test file message")

	// 等待文件写入
	time.Sleep(100 * time.Millisecond)

	// 验证文件存在并包含内容
	content, err := os.ReadFile(logFile)
	if err != nil {
		t.Fatalf("Failed to read log file: %v", err)
	}

	if !strings.Contains(string(content), "test file message") {
		t.Error("Expected log file to contain test message")
	}
}

func TestNewWithFileError(t *testing.T) {
	// 测试无效日志级别
	logger, err := NewWithFile("/tmp/test.log", "invalid_level")
	if err == nil {
		t.Error("Expected error for invalid log level, got nil")
	}
	if logger != nil {
		t.Error("Expected logger to be nil for invalid log level")
	}

	// 清理测试文件
	os.Remove("/tmp/test.log")
}

func TestInfo(t *testing.T) {
	// 使用缓冲区捕获输出
	var buf bytes.Buffer
	logger := New()
	logger.SetOutput(&buf)

	// 测试Info方法
	logger.Info("Test info message")
	output := buf.String()

	// 验证输出包含预期内容
	if !strings.Contains(output, "INFO") {
		t.Error("Expected output to contain INFO")
	}
	if !strings.Contains(output, "Test info message") {
		t.Error("Expected output to contain the log message")
	}

	// 测试Infof方法
	buf.Reset()
	logger.Infof("Test info message: %s", "hello")
	output = buf.String()

	if !strings.Contains(output, "Test info message: hello") {
		t.Error("Expected output to contain formatted message")
	}
}

func TestError(t *testing.T) {
	// 使用缓冲区捕获输出
	var buf bytes.Buffer
	logger := New()
	logger.SetOutput(&buf)

	// 测试Error方法
	logger.Error("Test error message")
	output := buf.String()

	// 验证输出包含预期内容
	if !strings.Contains(output, "ERRO") {
		t.Error("Expected output to contain ERRO")
	}
	if !strings.Contains(output, "Test error message") {
		t.Error("Expected output to contain the log message")
	}

	// 测试Errorf方法
	buf.Reset()
	logger.Errorf("Test error message: %d", 123)
	output = buf.String()

	if !strings.Contains(output, "Test error message: 123") {
		t.Error("Expected output to contain formatted message")
	}
}

func TestDebug(t *testing.T) {
	// 使用缓冲区捕获输出
	var buf bytes.Buffer
	logger := New()
	logger.SetOutput(&buf)
	logger.SetLevel("debug") // 确保debug级别被输出

	// 测试Debug方法
	logger.Debug("Test debug message")
	output := buf.String()

	// 验证输出包含预期内容
	if !strings.Contains(output, "DEBU") {
		t.Error("Expected output to contain DEBU")
	}
	if !strings.Contains(output, "Test debug message") {
		t.Error("Expected output to contain the log message")
	}

	// 测试Debugf方法
	buf.Reset()
	logger.Debugf("Test debug message: %v", true)
	output = buf.String()

	if !strings.Contains(output, "Test debug message: true") {
		t.Error("Expected output to contain formatted message")
	}
}

func TestWarn(t *testing.T) {
	// 使用缓冲区捕获输出
	var buf bytes.Buffer
	logger := New()
	logger.SetOutput(&buf)

	// 测试Warn方法
	logger.Warn("Test warning message")
	output := buf.String()

	// 验证输出包含预期内容
	if !strings.Contains(output, "WARN") {
		t.Error("Expected output to contain WARN")
	}
	if !strings.Contains(output, "Test warning message") {
		t.Error("Expected output to contain the log message")
	}

	// 测试Warnf方法
	buf.Reset()
	logger.Warnf("Test warning message: %f", 3.14)
	output = buf.String()

	if !strings.Contains(output, "Test warning message: 3.14") {
		t.Error("Expected output to contain formatted message")
	}
}

func TestFileLogging(t *testing.T) {
	// 创建临时目录
	tmpDir, err := os.MkdirTemp("", "test_file_logging_")
	if err != nil {
		t.Fatalf("Failed to create temp dir: %v", err)
	}
	defer os.RemoveAll(tmpDir)

	logFile := filepath.Join(tmpDir, "test.log")

	// 创建带文件的日志器
	logger, err := NewWithFile(logFile, "debug")
	if err != nil {
		t.Fatalf("Failed to create logger with file: %v", err)
	}

	// 记录各种类型的日志
	testMessage := "Test file logging message"
	logger.Info(testMessage)
	logger.Error(testMessage)
	logger.Debug(testMessage)
	logger.Warn(testMessage)

	// 等待文件写入
	time.Sleep(100 * time.Millisecond)

	// 读取文件内容
	content, err := os.ReadFile(logFile)
	if err != nil {
		t.Fatalf("Failed to read log file: %v", err)
	}

	contentStr := string(content)

	// 验证文件包含所有日志级别
	expectedLevels := []string{"level=info", "level=error", "level=debug", "level=warning"}
	for _, level := range expectedLevels {
		if !strings.Contains(contentStr, level) {
			t.Errorf("Expected log file to contain %s", level)
		}
	}

	// 验证文件包含测试消息
	if !strings.Contains(contentStr, testMessage) {
		t.Error("Expected log file to contain the test message")
	}
}

func TestLoggerInterface(t *testing.T) {
	// 测试Logger接口的实现
	var logger Logger = New()
	if logger == nil {
		t.Fatal("Expected logger to implement Logger interface")
	}

	// 设置输出到缓冲区进行测试
	var buf bytes.Buffer
	logger.SetOutput(&buf)

	// 测试接口方法
	logger.Info("Interface test")
	logger.Error("Interface test")
	logger.Debug("Interface test")
	logger.Warn("Interface test")

	// 测试格式化方法
	logger.Infof("Interface test %s", "formatted")
	logger.Errorf("Interface test %d", 123)

	// 验证有输出
	output := buf.String()
	if len(output) == 0 {
		t.Error("Expected some output from logger interface methods")
	}
}

func TestConcurrentLogging(t *testing.T) {
	// 测试并发日志记录
	logger := New()
	var buf bytes.Buffer
	logger.SetOutput(&buf)

	done := make(chan bool, 10)

	for i := 0; i < 10; i++ {
		go func(id int) {
			logger.Infof("Concurrent log message %d", id)
			logger.Errorf("Concurrent error message %d", id)
			logger.Debugf("Concurrent debug message %d", id)
			logger.Warnf("Concurrent warning message %d", id)
			done <- true
		}(i)
	}

	// 等待所有goroutine完成
	for i := 0; i < 10; i++ {
		<-done
	}

	// 验证没有panic，有一些输出
	output := buf.String()
	if len(output) == 0 {
		t.Error("Expected some output from concurrent logging")
	}
}

func TestLogFormatting(t *testing.T) {
	// 测试日志格式化
	logger := New()
	var buf bytes.Buffer
	logger.SetOutput(&buf)

	// 测试各种格式化 - 这些应该正常工作
	logger.Infof("String: %s, Int: %d, Float: %.2f, Bool: %v", "test", 42, 3.14, true)
	logger.Errorf("Error with %s", "formatting")
	logger.Debugf("Debug with %d numbers", 123)
	logger.Warnf("Warning with %v value", true)

	// 如果执行到这里没有panic，说明格式化工作正常
	output := buf.String()

	// 验证格式化内容存在
	if !strings.Contains(output, "String: test, Int: 42, Float: 3.14, Bool: true") {
		t.Error("Expected formatted string output")
	}
	if !strings.Contains(output, "Error with formatting") {
		t.Error("Expected formatted error output")
	}
}

func TestEmptyLogMessage(t *testing.T) {
	// 测试空日志消息 - 简化测试，只验证方法调用不panic
	logger := New()
	var buf bytes.Buffer
	logger.SetOutput(&buf)

	// 测试空消息 - 这些应该正常工作
	logger.Info("")
	logger.Error("")
	logger.Debug("")
	logger.Warn("")

	// 如果执行到这里没有panic，说明空消息处理正常
	output := buf.String()
	if len(output) == 0 {
		t.Error("Expected some output even for empty messages")
	}
}

// 测试结构化日志功能
func TestStructuredLogging(t *testing.T) {
	logger := New()
	var buf bytes.Buffer
	logger.SetOutput(&buf)

	// 禁用颜色输出以便测试
	logger.SetFormatter(&logrus.TextFormatter{
		DisableColors: true,
		FullTimestamp: true,
	})

	// 测试WithField
	logger.WithField("key", "value").Info("test message")
	output := buf.String()

	if !strings.Contains(output, "key=value") {
		t.Errorf("Expected output to contain structured field, got: %q", output)
	}
	if !strings.Contains(output, "test message") {
		t.Error("Expected output to contain message")
	}

	// 测试WithFields
	buf.Reset()
	logger.WithFields(map[string]interface{}{
		"user_id": 123,
		"action":  "login",
	}).Info("user action")

	output = buf.String()
	if !strings.Contains(output, "user_id=123") {
		t.Errorf("Expected output to contain user_id field, got: %q", output)
	}
	if !strings.Contains(output, "action=login") {
		t.Errorf("Expected output to contain action field, got: %q", output)
	}
}

// 测试WithError功能
func TestWithError(t *testing.T) {
	logger := New()
	var buf bytes.Buffer
	logger.SetOutput(&buf)

	testErr := errors.New("test error")
	logger.WithError(testErr).Error("something went wrong")

	output := buf.String()
	if !strings.Contains(output, "test error") {
		t.Error("Expected output to contain error message")
	}
	if !strings.Contains(output, "something went wrong") {
		t.Error("Expected output to contain log message")
	}
}

// 测试日志级别设置
func TestSetLevel(t *testing.T) {
	logger := New()
	var buf bytes.Buffer
	logger.SetOutput(&buf)

	// 设置为error级别
	err := logger.SetLevel("error")
	if err != nil {
		t.Fatalf("Failed to set log level: %v", err)
	}

	// info级别的日志应该被过滤掉
	logger.Info("this should not appear")
	logger.Error("this should appear")

	output := buf.String()
	if strings.Contains(output, "this should not appear") {
		t.Error("Info message should be filtered out at error level")
	}
	if !strings.Contains(output, "this should appear") {
		t.Error("Error message should appear at error level")
	}
}

// 测试JSON格式
func TestJSONFormat(t *testing.T) {
	logger, err := NewWithConfig("info", nil, "json")
	if err != nil {
		t.Fatalf("Failed to create JSON logger: %v", err)
	}

	var buf bytes.Buffer
	logger.SetOutput(&buf)

	logger.WithField("test_field", "test_value").Info("json test message")

	output := buf.String()
	// JSON格式应该包含这些元素
	if !strings.Contains(output, `"level":"info"`) {
		t.Error("Expected JSON to contain level field")
	}
	if !strings.Contains(output, `"test_field":"test_value"`) {
		t.Error("Expected JSON to contain custom field")
	}
	if !strings.Contains(output, `"msg":"json test message"`) {
		t.Error("Expected JSON to contain message field")
	}
}
